import Vue from 'vue'
import Cookie from 'js-cookie'
import i18n from '@/lang'
import store from '@/store'
import { getQueryObject, param, get1stHostName, stringFormat, generateUUID } from '@/utils'
import { getUserOpenidByCodeAPI, getUserUnionidByCodeAPI, mergeUserByCodeAPI } from '@/api/user'
import { getOfficalAccountAPI } from '@/api/wechat'

export const WXAUTH_GET_CODE_URL = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid={0}&redirect_uri={1}&response_type=code&scope={2}&state={3}&component_appid={4}#wechat_redirect'
export const SCOPE_SNSAPI_BASE = 'snsapi_base'
export const SCOPE_SNSAPI_USERINFO = 'snsapi_userinfo'
export const OPENID_COOKIE_NAME = 'openid'
export const HAS_UNIONID_COOKIE_NAME = 'has_unionid'


export function wechatMergeUserByCode(query, scope, cb) {
  if (!query.code || !query.state) {
    throw new Error('no code and noe state')
  }

  // let userinfoState = Cookie.get(SCOPE_SNSAPI_USERINFO)
  let userinfoState = Cookie.get(scope)
  if (userinfoState !== query.state) {
    Vue.$vux.alert.show({
      content: i18n.t('merge user failed: illegal state'),
      buttonText: i18n.t("tryAgainByClick"),
      onHide: () => {
        reloadWithoutCode(query)
      }
    })

    throw new Error('illegal state')
  }

  mergeUserByCodeAPI(query.code, scope)
    .then(({ data }) => {
      Vue.prototype.$weixin.ready(() => {

        cb && cb(data)
        Vue.prototype.$weixin.miniProgram.navigateBack()
      })
    })
    .catch((err) => {
      Vue.$vux.alert.show({
        content: 'illegal code: ' + err,
        buttonText: i18n.t("tryAgainByClick"),
        onHide: () => {
          reloadWithoutCode(query)
        }
      })
    })
}

export function wechatGetUnionidByCode(query) {

  if (!query.code || !query.state) {
    throw new Error('no code and noe state')
  }

  let userinfoState = Cookie.get(SCOPE_SNSAPI_USERINFO)
  if (userinfoState !== query.state) {
    Vue.$vux.alert.show({
      content: i18n.t('getUserInfoFailed: illegal state'),
      buttonText: i18n.t("tryAgainByClick"),
      onHide: () => {
        reloadWithoutCode(query)
      }
    })

    throw new Error('illegal state')
  }

  const hostname = get1stHostName()
  getUserUnionidByCodeAPI(hostname, query.code).then(({ data }) => {

    reloadWithoutCode(query)
  }).catch(err => {
    Vue.$vux.alert.show({
      content: 'illegal code: ' + err,
      buttonText: i18n.t("tryAgainByClick"),
      onHide: () => {
        reloadWithoutCode(query)
      }
    })
  })
}

export function wechatGetOpenid() {

  return new Promise((resolve, reject) => {

    const openid = getOpenid()
    if (openid) {
      return resolve(openid)
    }

    const query = getQueryObject()
    if (!query.code || !query.state) {

      // 没有code则换取code
      wechatGetCode(SCOPE_SNSAPI_BASE)
      return
    }

    // 如果URL有code等信息，说明是登陆链接，就通过api去换取用户openid
    const baseState = Cookie.get(SCOPE_SNSAPI_BASE)
    if (baseState !== query.state) {
      return reject('illegal state')
    }

    const hostname = get1stHostName()
    getUserOpenidByCodeAPI(query.code).then(({ data }) => {
      const { openid } = data

      if (!openid) {
        return reject('illegal code: cant get openid by code')
      }

      storeOpenid(openid)

      reloadWithoutCode(query)

    }).catch(err => {
      return reject(err)
    })

  })
}

export function wechatGetCode (scope) {
  const hostname = get1stHostName()

  // 这里调用该api不是为了获取城市信息，而是为了获取appid去换code
  getOfficalAccountAPI({ name: hostname }).then(({ data }) => {

    const { appid, component_appid } = data
    const state = generateUUID()
    const redirectUrl = encodeURIComponent(window.location.href)

    Cookie.set(scope, state)

    window.location.replace(stringFormat(WXAUTH_GET_CODE_URL, [appid, redirectUrl, scope, state, component_appid]))
  })
}

// 去掉code等敏感参数并重新加载页面
export function reloadWithoutCode(query = getQueryObject()) {

  Cookie.get(SCOPE_SNSAPI_BASE) && Cookie.remove(SCOPE_SNSAPI_BASE)
  Cookie.get(SCOPE_SNSAPI_USERINFO) && Cookie.remove(SCOPE_SNSAPI_USERINFO)

  delete query.code
  delete query.state
  delete query.appid

  let params = param(query)
  params = params.length <= 0 ? '' : ('?' + params)

  window.location.replace(window.location.origin + window.location.pathname + params)
}

export function getOpenid() {
  return Cookie.get(OPENID_COOKIE_NAME)
}

export function storeOpenid(openid) {
  Cookie.set(OPENID_COOKIE_NAME, openid, { expires: 365 * 100 })
}



